﻿using System;
using System.Collections.Generic;
using System.Threading;
using System.Windows.Controls;
using System.Windows.Input;
using DevExpress.Xpf.Core;
using ICSharpCode.AvalonEdit.Highlighting;
using DBAccessLibrary;
using ICSharpCode.AvalonEdit.CodeCompletion;
using DBAccessLibrary.Model;
using SQLQuery.Data;
using DevExpress.Xpf.Docking;
using QueryResource.ViewModel;
using System.Windows.Media;
using System.IO;
using System.Windows.Threading;
using ICSharpCode.AvalonEdit.Folding;
using SQLQuery.UI.SQLEdit;
using SQLQuery.Common;

namespace SQLQuery.UI
{
    /// <summary>
    /// SQLControl.xaml 的交互逻辑
    /// </summary>
    [System.ComponentModel.DesignTimeVisible(false)]
    public partial class SQLControl : DockPanel
    {
        //下拉窗口
        private CompletionWindow completionWindow = null;  
        //查找替换
        FindReplace.FindReplaceMgr FRM = new FindReplace.FindReplaceMgr();
        private int _hashCode    = 0;//当前文本的哈希值
        public SQLControl()
        {
            InitializeComponent();
            ViewModel = new SqlViewModel();
            ViewModel.AppendText = AppendCmd;
            this.textEditor1.TextArea.TextEntered += textEditor_TextArea_TextEntered;
            this.textEditor1.TextArea.TextEntering += textEditor_TextArea_TextEntering;

            FRM.CurrentEditor = new FindReplace.TextEditorAdapter(this.textEditor1);
            FRM.ShowSearchIn = false;
            //FRM.OwnerWindow = this;

            CommandBindings.Add(FRM.FindBinding);
            CommandBindings.Add(FRM.ReplaceBinding);
            CommandBindings.Add(FRM.FindNextBinding);
            Loaded += SqlControlLoaded;
            this.SizeChanged += new System.Windows.SizeChangedEventHandler(SqlControlSizeChanged);
        }

        void SqlControlSizeChanged(object sender, System.Windows.SizeChangedEventArgs e)
        {
            //窗体大小改变时  滚动条始终在末尾
            ScrollToEnd();
        }

        void SqlControlLoaded(object sender, System.Windows.RoutedEventArgs e)
        {
            //当窗体打开时  默认光标显示
            ThreadPool.QueueUserWorkItem(o =>
            {
                Thread.Sleep(300);
                this.InvokeEx(() => textEditor1.Focus());
                DispatcherHelper.DoEvents();
            });
        }

        public SqlViewModel ViewModel { get; set; }
        public void Init(bool isLoadFile,bool isScollToEnd = true)
        {
            
                ViewModel.GetFontName = () => this.textEditor1.FontFamily.Source;
                ViewModel.GetFontSize = () => this.textEditor1.FontSize;
                ViewModel.GetMaxWidth = () => this.textEditor1.ViewportWidth;
                ViewModel.GetSelectText = () => this.textEditor1.SelectedText;
                ViewModel.SetSelectText = text => this.textEditor1.SelectedText = text;

                this.DataContext = ViewModel;

                this.textEditor1.SyntaxHighlighting = HighlightingManager.Instance.GetDefinition("SQL");
                if (isLoadFile)
                {
                    if (File.Exists(System.AppDomain.CurrentDomain.BaseDirectory + "\\文档.txt"))
                    {
                        this.LoadFile(System.AppDomain.CurrentDomain.BaseDirectory + "\\文档.txt");
                        if (isScollToEnd)
                        {
                            ScrollToEnd();
                        }
                    }
                }

                //启用折叠
                //FoldingInit();
           
        }

        #region 事件
        private void textEditor1_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.F5)
            {
                //ViewModel.F5Command.Execute(null);
            }
            else if((e.KeyStates == Keyboard.GetKeyStates(Key.S) && Keyboard.Modifiers == ModifierKeys.Control) ||
               e.Key == Key.Left || e.Key == Key.Right || e.Key == Key.Down || e.Key == Key.Up ||
                Keyboard.Modifiers != ModifierKeys.None)
            {
            }
            else
            {
                
                DocumentPanel dp = this.Tag as DocumentPanel;
                if (dp != null && dp.Caption.IndexOf('*') < 0)
                {
                    if (_hashCode != this.textEditor1.Text.GetHashCode())
                    {
                        dp.Caption += "*";
                    }
                }
            }

        }
        private void textEditor1_KeyUp(object sender, KeyEventArgs e)
        {
            //增加 通过快捷键来快速 拼接SQL语句
            if (e.Key == Key.Tab)
            {
                TabCaret();
            }
            DocumentPanel dp = this.Tag as DocumentPanel;
            bool isNotChange = dp != null && dp.Caption.IndexOf('*') < 0;


            if (isNotChange)
            {
                if (_hashCode != this.textEditor1.Text.GetHashCode())
                {
                    dp.Caption += "*";
                }
            }
            else
            {
                if (_hashCode == this.textEditor1.Text.GetHashCode())
                {
                    dp.Caption = dp.Caption.Replace("*", "");
                }
            }

        }

        /// <summary>
        /// tab 快捷信息
        /// </summary>
        private void TabCaret()
        {
            string key = string.Empty;
            if (this.textEditor1.CaretOffset <= 2)
            {
                int index = this.textEditor1.CaretOffset - 2;
                key = this.textEditor1.Text.Substring(index, 1);
            }
            else
            {
                int index = this.textEditor1.CaretOffset - 3;
                key = this.textEditor1.Text.Substring(index, 2);
            }
            string repl = string.Empty;
            if (key.EndsWith("\t") || key.EndsWith("\n"))
            { return; }
            repl = DBOperatorFactory.GetSqlGrammar.AppendTabText(key);

            if (repl != string.Empty)
            {
                int count = key.Trim().Length + 1;
                int index = this.textEditor1.CaretOffset - count;
                textEditor1.Select(index, count);
                textEditor1.SelectedText = repl;
                textEditor1.Select(index + repl.Length, 0);
            }
        }
        private void textEditor_TextArea_TextEntered(object sender, TextCompositionEventArgs e)
        { 
            //查找出关键字
            //string content = this.textEditor1.Text.Substring(0, this.textEditor1.CaretOffset);
               
            if (e.Text == ".")
            {
                //检索表实体
                TableEntity table = ViewModel.TextEnteredPoint(this.textEditor1.Text, this.textEditor1.CaretOffset);

                if (table != null)
                {
                    completionWindow = new CompletionWindow(this.textEditor1.TextArea);
                    IList<ICompletionData> data = completionWindow.CompletionList.CompletionData;
                    foreach (FieldEntity field in table.FileNodes)
                    {
                        data.Add(new FieldCompletionData(field));
                    }

                    completionWindow.Show();
                    completionWindow.Closed += delegate
                    {
                        completionWindow = null;
                    };
                }
            }
            else if (e.Text == " ")
            {
                IEnumerable<DataBaseEntity> list = ViewModel.TextEnteredSpace(this.textEditor1.Text, this.textEditor1.CaretOffset);

                if (list != null)
                {
                    completionWindow = new CompletionWindow(this.textEditor1.TextArea);
                    IList<ICompletionData> data = completionWindow.CompletionList.CompletionData;
                    foreach (DataBaseEntity table in list)
                    {
                        data.Add(new FieldCompletionData(table));
                    }
                    completionWindow.CloseAction = obj => 
                    {
                        FieldCompletionData field = obj as FieldCompletionData;
                        if (field != null)
                        {
                            string text = DBOperatorFactory.GetSqlGrammar.GetProcParamInfo(SysCache.DBConnection.ConnectType,field.DBEntity as ProcEntity);
                            if (!string.IsNullOrEmpty(text))
                            {
                                this.AppendCaretCmd(text);
                            }
                        }
                    };
                    completionWindow.Show();
                    completionWindow.Closed += delegate
                    {
                        completionWindow = null;
                    };
                }
            }
        }

        private void textEditor_TextArea_TextEntering(object sender, TextCompositionEventArgs e)
        {
            //if (e.Text.Length > 0 && completionWindow != null)
            //{
            //    if (!char.IsLetterOrDigit(e.Text[0]))
            //    {
            //        completionWindow.CompletionList.RequestInsertion(e);
            //    }
            //}
        }
        //格式刷
        private void Format_CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = !string.IsNullOrEmpty(ViewModel.SelectText);
        }
        private void Format_CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            this.textEditor1.SelectedText = ViewModel.SqlFormatPainter(this.textEditor1.SelectedText, true);
        }
        //转换成C# 拼接语句
        private void Splice_CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = !string.IsNullOrEmpty(ViewModel.SelectText);
        }
        private void Splice_CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            ViewModel.SqlSplicePainter();
        }
      
        //定位
        private void Position_CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            //如果所选择的内容是表名 则可用
            //e.CanExecute = ViewModel.IsPositionTable;
            e.CanExecute = true;
        }
        private void Position_CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            //定位到 树中该节点
            ViewModel.PositionTable();
        }
        //智能提示
        private void Query_CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            //显示所有表
            ShowAllTable();
        }
        //注释
        private void zhushi_CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            int start = this.textEditor1.Document.GetLineByOffset(this.textEditor1.CaretOffset).Offset;
            int end = this.textEditor1.CaretOffset;
            int index = this.textEditor1.Document.GetText(start, end - start).IndexOf("--");
            if (index == -1)
            {
                this.textEditor1.Document.Insert(this.textEditor1.Document.GetLineByOffset(this.textEditor1.CaretOffset).Offset, "--");
            }

            if (this.textEditor1.SelectedText != string.Empty && this.textEditor1.SelectedText.IndexOf(Environment.NewLine) > 0)
            {
                string text = this.textEditor1.SelectedText.Replace(Environment.NewLine + "--", Environment.NewLine);
                this.textEditor1.SelectedText = text.Replace(Environment.NewLine, Environment.NewLine + "--");
            }
        }
        //反注释
        private void NoZhushi_CommandBinding_Excuted(object sender, ExecutedRoutedEventArgs e)
        {
            int start = this.textEditor1.Document.GetLineByOffset(this.textEditor1.SelectionStart).Offset;
            int end = this.textEditor1.SelectionStart;
            int index = this.textEditor1.Document.GetText(start, end - start).IndexOf("--");

            if (index != -1)
            {
                this.textEditor1.Document.Remove(start + index, 2);
            }
            if (this.textEditor1.SelectedText != string.Empty && this.textEditor1.SelectedText.IndexOf(Environment.NewLine) > 0)
            {
                this.textEditor1.SelectedText = this.textEditor1.SelectedText.Replace("--", "");
            }
        }
        #endregion

        /// <summary>
        /// 是否是新建（如果新建需要保存）
        /// </summary>
        public bool IsNewDocument { get; set; }
        public string FilePath { get; set; }

        /// <summary>
        /// 显示智能提示 表信息
        /// </summary>
        private void ShowAllTable()
        {
            IEnumerable<DataBaseEntity> list = SysCache.TableList;
            if (list != null)
            {
                completionWindow = new CompletionWindow(this.textEditor1.TextArea);
                IList<ICompletionData> data = completionWindow.CompletionList.CompletionData;
                foreach (DataBaseEntity table in list)
                {
                    data.Add(new FieldCompletionData(table));
                }
                completionWindow.Show();
                completionWindow.Closed += delegate
                {
                    completionWindow = null;
                };
            }
        }

        /// <summary>
        /// 读取文件的数据
        /// </summary>
        /// <param name="fileName"></param>
        public void LoadFile(string fileName)
        {
            if (!string.IsNullOrEmpty(fileName))
            {
                this.textEditor1.Load(fileName);
                this.FilePath = fileName;
                _hashCode = this.textEditor1.Text.GetHashCode();
            }
        }
        public void LoadText(string text)
        {
            AppendCmd(text);
            _hashCode = this.textEditor1.Text.GetHashCode();
        }
        /// <summary>
        /// 保存数据到文件
        /// </summary>
        /// <param name="fileName"></param>
        public void SaveFile(string fileName)
        {
            if (!string.IsNullOrEmpty(fileName))
            {
                if (!Directory.Exists(Path.GetDirectoryName(fileName)))
                {
                    Directory.CreateDirectory(Path.GetDirectoryName(fileName));
                }
                this.textEditor1.Save(fileName);
                _hashCode = this.textEditor1.Text.GetHashCode();
            }
        }
        public void RemoveFile()
        {
            if (IsNewDocument)
            {
               
                DocumentPanel panel = this.Tag as DocumentPanel;
                if(panel != null)
                {
                    string filename = System.AppDomain.CurrentDomain.BaseDirectory + "\\Temporary\\" +
                                 panel.Caption.Replace("*", "");
                    if (File.Exists(filename))
                    {
                        File.Delete(filename);
                    }
                }
              
            }
        }
        /// <summary>
        /// 换行 添加信息到末尾
        /// </summary>
        /// <param name="msg"></param>
        public void AppendCmd(string msg)
        {
            this.textEditor1.BeginInvokeEx(new Action(() =>
            {
                this.textEditor1.AppendText(msg);
                ScrollToEnd();
            }), null);
        }
        /// <summary>
        /// 添加信息到光标处
        /// </summary>
        /// <param name="msg"></param>
        public void AppendCaretCmd(string msg)
        {
            this.textEditor1.BeginInvokeEx(new Action(() =>
            {
                this.textEditor1.AppendOfficeText(msg);
            }), null);
        }
        /// <summary>
        /// 光标移动到末尾
        /// </summary>
        private void ScrollToEnd()
        {
            this.textEditor1.ScrollToEnd();
            this.textEditor1.CaretOffset = this.textEditor1.Text.Length;
        }
        /// <summary>
        /// 清空
        /// </summary>
        public void Clear()
        {
            this.textEditor1.Clear();
        }

        private void cbFont_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            this.textEditor1.FontFamily = new FontFamily(e.AddedItems[0].ToString());
        }

        private void cbFontSize_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            this.textEditor1.FontSize = Convert.ToDouble(e.AddedItems[0].ToString());
        }

        #region 折叠
        FoldingManager foldingManager;
        AbstractFoldingStrategy foldingStrategy;
        private void FoldingInit()
        {
            DispatcherTimer foldingUpdateTimer = new DispatcherTimer();
            foldingUpdateTimer.Interval = TimeSpan.FromSeconds(2);
            foldingUpdateTimer.Tick += foldingUpdateTimer_Tick;
            foldingUpdateTimer.Start();

            this.textEditor1.TextArea.IndentationStrategy = new ICSharpCode.AvalonEdit.Indentation.CSharp.CSharpIndentationStrategy(textEditor1.Options);
            foldingStrategy = new SqlFoldingStrategy();

            if (foldingStrategy != null)
            {
                if (foldingManager == null)
                    foldingManager = FoldingManager.Install(this.textEditor1.TextArea);
            }
            else
            {
                if (foldingManager != null)
                {
                    FoldingManager.Uninstall(foldingManager);
                    foldingManager = null;
                }
            }
        }
        void foldingUpdateTimer_Tick(object sender, EventArgs e)
        {
            if (foldingStrategy != null)
            {
                foldingStrategy.UpdateFoldings(foldingManager, this.textEditor1.Document.Text);
            }
        }
        #endregion
    }
}
